home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / ldb.zip / SBINDER.CPP < prev    next >
C/C++ Source or Header  |  1991-10-18  |  11KB  |  545 lines

  1. /*
  2.  
  3.     sbinder.cpp
  4.     10-18-91
  5.     Streamable Binder: Loose Data Binder v 1.4
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072 USA
  14.  
  15.     John Small
  16.     Voice: (703) 759-3838
  17.     CIS: 73757,2233
  18.  
  19. */
  20.  
  21.  
  22. #include <string.h>
  23. #include "sbinder.hpp"
  24.  
  25.  
  26. void Streamable::lserror(const char *msg, unsigned id)
  27. {
  28.     if (streamDebug)
  29.         cerr << endl
  30.             << "Class id: " << setw(6) << id
  31.             <<  "   stream error - "
  32.             << msg << endl;
  33. }
  34.  
  35. void Streamable::serror(const char *msg)
  36. {
  37.     if (streamDebug)
  38.         cerr << endl
  39.             <<"Class id: " << setw(6) << id
  40.             << "    &instance:   "
  41.             << (void *) this << endl
  42.             <<  "Stream error - "
  43.             << msg << endl;
  44. }
  45.  
  46. void Streamable::swarn(const char *msg)
  47. {
  48.     if (streamDebug)
  49.         cerr << endl
  50.             << "Class id: " << setw(6) << id
  51.             << "    &instance:   "
  52.             << (void *) this << endl
  53.             <<  "Stream warning - "
  54.             << msg << endl;
  55. }
  56.  
  57.  
  58. #pragma argsused
  59. StreamablE Streamable::load(istream& is,
  60.     StreamablE InstancE)
  61.     { return InstancE; }
  62.  
  63. int  Streamable::refDebug = 0;
  64. int  Streamable::streamDebug = 0;
  65. char Streamable::memberTermChar = '\n';
  66.  
  67. #pragma argsused
  68. Streamable::Streamable(StreamableClassRegistry& dummy,
  69.     unsigned id)
  70. {
  71.     parenT = voiD0;
  72.     this->id = id;
  73.     refCount = streamCount = 0;
  74.     streamPos = 0L;
  75. }
  76.  
  77. void Streamable::registerClass(unsigned id,
  78.         StreamablE (*loader)(istream& is,
  79.         StreamablE InstancE))
  80. {
  81.     SCRegistry.registerClass(id,loader);
  82. }
  83.  
  84. unsigned Streamable::restream()
  85. {
  86.     unsigned underFlow = (streamPos? 
  87.         refCount - streamCount : 0);
  88.     
  89.     streamCount = 0; 
  90.     streamPos = 0L;
  91.     if (underFlow)
  92.         swarn("restream: streamed less than "
  93.             "referenced");    
  94.     return underFlow;
  95. }
  96.  
  97. unsigned Streamable::unlink(voiD P)
  98. {
  99.     if (refDebug)
  100.         if (refCount)
  101.             cerr << endl
  102.             << "Class id: " << setw(6) << id
  103.             << "    &instance:   "
  104.             << (void *) this << endl
  105.             <<  "Unlinking, starting refCount: "
  106.             << refCount << endl;
  107.         else
  108.             cerr << endl
  109.             << "Class id: " << setw(6) << id
  110.             << "    &instance:   "
  111.             << (void *) this << endl
  112.             <<  "unlink() underflow" << endl;
  113.     if (refCount)
  114.         --refCount;
  115.     if (parenT == P || !refCount)
  116.         parenT = voiD0;
  117.     return refCount;
  118. }
  119.  
  120. StreamablE Streamable::link(voiD P)
  121. {
  122.     if (refCount >= UINT_MAX)  {
  123.         if (refDebug)
  124.             cerr << endl
  125.             << "Class id: " << setw(6) << id
  126.             << "    &instance:   "
  127.             << (void *) this << endl
  128.             <<  "link() overflow" << endl;
  129.         return StreamablE0;
  130.     }
  131.     refCount++;
  132.     if (!parenT && P)
  133.         parenT = P;
  134.     if (refDebug)
  135.         cerr << endl
  136.             << "Class id: " << setw(6) << id
  137.             << "    &instance:   "
  138.             << (void *) this << endl
  139.             <<  "Adding link, new refCount: "
  140.             << refCount << endl;
  141.     return this;
  142. }
  143.  
  144. ostream& endm(ostream& os)
  145. {
  146.     return os << Streamable::memberTermChar
  147.         << flush;
  148. }
  149.  
  150. istream& nextm(istream& is)
  151. {
  152.     is.get();
  153.     return is;
  154. }
  155.  
  156. int SBinder::Dfree(voiD D)
  157. {
  158.     if (D)  {
  159.         if (!((StreamablE)D)->RefCount())
  160.             delete (StreamablE) D;
  161.         return 1;
  162.     }
  163.     return 0;
  164. }
  165.  
  166. int SBinder::Dattach(voiD D)
  167. {
  168.     return ((((StreamablE)D)->link(this))? 1 : 0);
  169. }
  170.  
  171. void SBinder::Ddetach(voiD D)
  172. {
  173.     ((StreamablE)D)->unlink(this);
  174. }
  175.  
  176. ostream& SBinder::store(ostream& os)
  177. {
  178.     unsigned i;
  179.  
  180.     os << maxNodes << endm << limit << endm
  181.         << delta << endm << nodes << endm
  182.         << curNode << endm << flags << endm
  183.         << FncPtrToID((GenericFnC)comparE) << endm;
  184.     if (!os)
  185.         serror("unable to store Streamable Binder");
  186.     else for (i = 0; i < nodes; i++)
  187.         Dstore(os,atGet(i));
  188.     return os;
  189. }
  190.  
  191. StreamablE SBinder::load(istream& is, StreamablE InstancE)
  192. {
  193.     unsigned i, maxNodes, limit, delta, nodes, curNode;
  194.     unsigned flags;
  195.     unsigned comparEID;
  196.  
  197.     is >> maxNodes >> nextm >> limit >> nextm
  198.         >> delta >> nextm >> nodes >> nextm
  199.         >> curNode >> nextm >> flags >> nextm
  200.         >> comparEID >> nextm;
  201.     if (!is)  {
  202.         lserror("unable to load Streamable Binder "
  203.             "header data",
  204.             ID_CLASS);
  205.         return StreamablE0;
  206.     }
  207.     flags |= BDR_OK_FREE; // reloaded nodes are dynamic!
  208.     if (!InstancE)
  209.         if ((InstancE = (StreamablE)
  210.             new SBinder(UNIQUE_STREAMABLE))
  211.             == StreamablE0)  {
  212.             lserror("unable to construct "
  213.                 "Streamable Binder for "
  214.                 "loading",ID_CLASS);
  215.             return StreamablE0;
  216.         }
  217.     ((SBindeR)InstancE)->construct(flags,maxNodes,
  218.         limit,delta);
  219.     StreamablE D;
  220.     for (i = 0; i < nodes; i++)
  221.         ((SBindeR)InstancE)->insQ(
  222.             ((SBindeR)InstancE)->Dload(is));
  223.     ((SBindeR)InstancE)->setCurNode(curNode);
  224.     ((SBindeR)InstancE)->setComparE((BDRcomparE)
  225.         IDtoFncPtr(comparEID));
  226.     return InstancE;
  227. }
  228.  
  229. void SBinder::Dstore(ostream& os, const voiD D)
  230.     { os << (StreamablE) D; }
  231.  
  232. voiD SBinder::Dload(istream& is)
  233. {
  234.     StreamablE InstancE = StreamablE0;
  235.     
  236.     is >> InstancE;
  237.     return (voiD) InstancE;
  238. }
  239.  
  240. unsigned SBinder::restream()
  241. {
  242.     unsigned result = Streamable::restream();
  243.     for (unsigned i = 0; i < nodes; i++)
  244.         ((StreamablE)atGet(i))->restream();
  245.     return result;
  246. }
  247.  
  248. SBinder::~SBinder()
  249. {
  250.     if (flags & BDR_OK_FREE)
  251.         allFree();
  252.     else
  253.         allDel();
  254. }
  255.  
  256.  
  257. StreamableClassRegistry SCRegistry;
  258.  
  259. int StreamableClassRegistry::debug = 0;
  260.  
  261. void StreamableClassRegistry::error(char *msg, unsigned id,
  262.     StreamablE InstancE)
  263. {
  264.     if (debug)
  265.         cerr << endl
  266.             << "Class id: " << setw(6) << id
  267.             << "    &instance:   "
  268.             << (void *) InstancE << endl
  269.             << "ClassRegistry error - "
  270.             << msg << endl;
  271. }
  272.  
  273. void StreamableClassRegistry::warn(char *msg, unsigned id,
  274.     StreamablE InstancE)
  275. {
  276.     if (debug)
  277.         cerr << endl
  278.             << "Class id: " << setw(6) << id
  279.             << "    &instance:   "
  280.             << (void *) InstancE << endl
  281.             << "ClassRegistry warning - "
  282.             << msg << endl;
  283. }
  284.  
  285. unsigned StreamableClassRegistry::restream()
  286. {
  287.  
  288.     unsigned underFlow = InstanceLinks.Nodes();
  289.     IHRecorD R;
  290.  
  291.     for (unsigned i = 0; i < underFlow; i++)  {
  292.         R = (IHRecorD) InstanceLinks.atGet(i);
  293.         warn("Restream: holding pen under-linked",
  294.             R->InstancE->id,R->InstancE);
  295.     }
  296.     InstanceLinks.allFree();
  297.     return underFlow;
  298. }
  299.  
  300. void StreamableClassRegistry::registerClass(unsigned id,
  301.     StreamablE (*loader) (istream& is,
  302.     StreamablE InstancE))
  303. {
  304.     unsigned i;
  305.  
  306.     for (i = 0; i < ClassRecords.Nodes(); i++)
  307.         if (((SCRecorD)ClassRecords[i])->id
  308.             == id)
  309.             break;
  310.     if (i < ClassRecords.Nodes())
  311.         if (((SCRecorD)ClassRecords[i])->load
  312.             == loader)  {
  313.             warn("multiple registration of"
  314.                 " loader",id);
  315.             return;
  316.         }
  317.         else  {
  318.             error("id conflict: ",id);
  319.             return;
  320.         }
  321.     SCRecorD R = new StreamableClassRecord(id,loader);
  322.     if (!R)
  323.         error("class record memory exhausted",
  324.             id);
  325.     else if (!ClassRecords.insQ(R))  {
  326.         error("class record can't be queued",
  327.             id);
  328.         delete R;
  329.     }
  330. }
  331.  
  332. void StreamableClassRegistry::forgetClasses()
  333. {
  334.     ClassRecords.allFree();
  335.     InstanceLinks.allFree();
  336. }
  337.  
  338. istream& StreamableClassRegistry::get(istream& is,
  339.     StreamablE& InstancE)
  340. {
  341.     unsigned id, refCount, i;
  342.     long streamPos;
  343.     IHRecorD R;
  344.  
  345.     InstancE = StreamablE0;
  346.     if (!(is >> id >> nextm))  {
  347.         error("unable to read id");
  348.         return is;
  349.     }
  350.     if (id == ID_StreamableRef)  {
  351.         // link to previously loaded Instance
  352.         if (!(is >> streamPos >> nextm))  {
  353.             error("unable to read streamPos");
  354.             return is;
  355.         }
  356.         for (i = 0; i < InstanceLinks.Nodes(); i++)
  357.             if ((R = (IHRecorD)InstanceLinks[i])
  358.                 ->streamPos == streamPos)  {
  359.                 // found saved instance!
  360.                 InstancE = R->InstancE;
  361.                 if (R->refCount <= ++R->streamCount)
  362.                     // discard when done!
  363.                     InstanceLinks.atDel(i);
  364.                 break;
  365.             }
  366.         if (!InstancE)
  367.             error("unable to establish link to"
  368.                 " previously loaded class",
  369.                 id);
  370.     }
  371.     else  {  // load instance
  372.         streamPos = is.tellg();
  373.         if (!(is >> refCount >> nextm))  {
  374.             error("unable to read refCount",id);
  375.             return is;
  376.         }
  377.         for (i = 0; i < ClassRecords.Nodes(); i++)
  378.             if (((SCRecorD)ClassRecords[i])->id
  379.                 == id)
  380.                 break;
  381.         if (i >= ClassRecords.Nodes())  {
  382.             error("attempted load of unknown "
  383.                 "class",id);
  384.             return is;
  385.         }
  386.         if ((InstancE = (*((SCRecorD)
  387.             ClassRecords[i])->load)
  388.             (is,StreamablE0)) == StreamablE0)
  389.         {
  390.             error("unable to l